package com.ingenico.insider.services.impl;

import java.lang.reflect.Constructor;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.ingenico.tools.data.sampling.AverageDoublePathSampler;
import com.ingenico.tools.data.sampling.MaxDoublePathSampler;
import com.ingenico.tools.data.sampling.MinDoublePathSampler;
import com.ingenico.tools.data.sampling.NaiveDoublePathSampler;
import com.ingenico.tools.data.sampling.PathSampler;

public final class SubSamplingStrategySupplier {
	private static final Logger _logger = Logger.getLogger(SubSamplingStrategySupplier.class.getCanonicalName()); 

	/**
	 * singleton instance
	 */
	private static SubSamplingStrategySupplier instance;

	/**
	 * The list of path sampling strategies that are made available to the user 
	 */
	private static final Set<Class<?>> availableStrategies = new HashSet<Class<?>>();

	/**
	 * The default strategy class that should be supplied when no strategy is requested...
	 */
	private static final Class<?> defaultStrategyClass = AverageDoublePathSampler.class;

	/**
	 * private constructor of final class to prevent external instantiation
	 */
	private SubSamplingStrategySupplier() {
		initPathSampler();
	};

	/**
	 * Simple internal initialization of the strategies set
	 */
	private void initPathSampler() {
		availableStrategies.add(AverageDoublePathSampler.class);
		availableStrategies.add(NaiveDoublePathSampler.class);
		availableStrategies.add(MinDoublePathSampler.class);
		availableStrategies.add(MaxDoublePathSampler.class);
	}

	/**
	 * retrieve the singleton instance
	 *
	 * @return the SubSamplingStrategySupplier singleton
	 */
	public static SubSamplingStrategySupplier getInstance() {
		if (instance == null) {
			_logger.info(SubSamplingStrategySupplier.class.getName() + " instance does not exist... Creating instance.");
			instance = new SubSamplingStrategySupplier();
		}
		return instance;
	}

	/**
	 * Gives the list of available path sampler strategies.
	 * 
	 *  These strategies should not be created directly.
	 *
	 * @return the list of strategy classes
	 * @see SubSamplingStrategySupplier#buildStrategy(Class)
	 */
	public Set<Class<?>> getAvailableStrategies() {
		return availableStrategies;
	}

	/**
	 * Gives a default path sampler strategy
	 * 
	 * The class instance has to be created by the client 
	 * 
	 * @return the class used as the default strategy
	 * @see SubSamplingStrategySupplier#buildStrategy(Class)
	 */
	public Class<?> getDefaultStrategy() {
		return defaultStrategyClass;
	}

	/**
	 * Build a strategy from its class...
	 * 
	 * Strategies could be created by using their constructor however
	 * using this factory ensures that all parameters are correctly
	 * initialized if required...
	 * 
	 * @param strategyClass
	 * @return an instance of the strategy or null if an error occured...
	 */
	public PathSampler buildStrategy(Class<?> strategyClass) {
		if (strategyClass == null) {
			strategyClass = defaultStrategyClass;
		}

		try {
			Constructor<?> c = strategyClass.getConstructor(new Class[]{});
			return (PathSampler)c.newInstance((Object[])null);
		} catch (Exception e) {
			// This is rather general, but we will only display a generic message anyway...
			_logger.log(Level.SEVERE, e.getMessage(), e);
			MessageBoxSupplier.getInstance().showErrorDialog(MessageBoxSupplier.GENERAL_ERROR_KEY, e);
		}
		return null;
	}
}